package com.csjy.migration.hnnd.business;

import com.csjy.migration.hnnd.DbUtil;
import com.csjy.migration.hnnd.ProgramArgument;
import com.csjy.migration.hnnd.StrongUuidGenerator;
import com.csjy.migration.hnnd.Tool;
import com.csjy.migration.hnnd.annotation.BusinessDataConverter;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 基础数据转换抽象类
 */
public abstract class AbstractBusiness {
  protected DbUtil sourceDbUtil;
  protected DbUtil targetDbUtil;
  protected SourceBusinessData sourceData;
  protected ProgramArgument programArgument;
  protected String projectId;

  protected String insertSql = null;
  protected String updateSql = null;
  protected String findMigratedIdListSql = null;

  protected List<Object> migratedIdList = new ArrayList<>();
  protected List<List> batchUpdateValues = new ArrayList<>();
  protected List<List> batchInsertValues = new ArrayList<>();
  protected StrongUuidGenerator uuidGenerator = new StrongUuidGenerator();


  public AbstractBusiness(DbUtil sourceDbUtil, DbUtil targetDbUtil, SourceBusinessData sourceData, ProgramArgument programArgument, String projectId) throws SQLException {
    this.sourceDbUtil = sourceDbUtil;
    this.targetDbUtil = targetDbUtil;
    this.sourceData = sourceData;
    this.projectId = projectId;
    this.programArgument = programArgument;
    this.readAnnotationValue();
    this.findMigratedIdList();
  }

  public AbstractBusiness(DbUtil sourceDbUtil, DbUtil targetDbUtil, SourceBusinessData sourceData, ProgramArgument programArgument, String projectId, boolean findMigratedIdListBySelf) throws SQLException {
    this.sourceDbUtil = sourceDbUtil;
    this.targetDbUtil = targetDbUtil;
    this.sourceData = sourceData;
    this.projectId = projectId;
    this.programArgument = programArgument;
    this.readAnnotationValue();
    if(!findMigratedIdListBySelf) {
      this.findMigratedIdList();
    }
  }

  public void readAnnotationValue() throws SQLException {
    BusinessDataConverter businessDataConverter = this.getClass().getAnnotation(BusinessDataConverter.class);
    this.insertSql = businessDataConverter.insertSql() ;
    this.updateSql = businessDataConverter.updateSql();
    this.findMigratedIdListSql = businessDataConverter.findMigratedIdListSql();
  }

  public void findMigratedIdList() throws SQLException {
    // 查询已迁移的记录
    this.migratedIdList = this.targetDbUtil.selectSingleColumn(findMigratedIdListSql,Arrays.asList(new String[]{this.projectId}));
  }

  public void start() throws Exception {
    System.out.println("开始迁移"+this.getClass().getSimpleName()+"表...");
    try {

      this.migrate();
      if (this.batchUpdateValues.size() > 0) {
        this.targetDbUtil.updateByParamsBatch(this.updateSql, this.batchUpdateValues, true);
      }
      if (this.batchInsertValues.size() > 0) {
        this.targetDbUtil.updateByParamsBatch(this.insertSql, this.batchInsertValues, false);
      }

      System.out.println(this.getClass().getSimpleName() + "表迁移完成.");
    }catch(Exception e) {
      throw new Exception(this.getClass().getSimpleName() +"表迁移失败："+e.getMessage());
    }
  }

  public abstract void migrate() throws Exception;

  /**
   * 判断是否需要迁移
   *
   * @param targetIdFieldName
   * @param targetId
   * @return
   * @throws SQLException
   */
  @Deprecated
  public boolean needMigrated(String targetIdFieldName, String targetId) throws SQLException {
    if(this.programArgument.getCover().equals("1")) {
      return true;
    }
    List<Map> result =targetDbUtil.selectByParams("SELECT COUNT(*) COUNT_ FROM "+Tool.camelCaseToUpperCaseWithUnderline(this.getClass().getSimpleName())+" WHERE "+targetIdFieldName+" = ? ", Arrays.asList(new String[]{targetId}));
    if(Integer.valueOf(result.get(0).get("COUNT_").toString()) == 0){
      return true;
    }
    return false;
  }

  /**
   * 最新判断是否需要迁移方法
   * @param targetId
   * @return
   */
  public int needMigrated(String targetId) {
    boolean exists = this.migratedIdList.contains(targetId);
    if (this.programArgument.getCover().equals("0") && exists) {
      return 0;
    }
    return exists ? 1 : 2;
  }

  public String getCustomSourceId(String ...args) {

    if(args == null || args.length == 0){
      throw new Error("getCustomSourceId无效参数");
    }

    return this.projectId + "-" + Arrays.stream(args).collect(Collectors.joining("-")) + "-" + this.getClass().getSimpleName();

  }

  public String getCustomSourceIdWithoutFix(String ...args) {

    if(args == null || args.length == 0){
      throw new Error("getCustomSourceId无效参数");
    }

    return  Arrays.stream(args).collect(Collectors.joining("-"));

  }
  //字符串时间转换成时间戳id
  public String getSimpleId(String args,String proId) throws Exception {
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    return String .valueOf(formatter.parse(args).getTime()/1000)+proId;

  }
}
